﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using ERP.Team.ProductionSystem;
using ERP.Common.DTO;
using DocumentFormat.OpenXml.EMMA;

namespace ERP.ERPSystem.ProductionSystem.MaterialTypes
{
    /// <summary>
    /// 物料产品分类实现类
    /// </summary>
    public class MaterialTypeService : ApplicationService, IMaterialTypeService
    {
        /// <summary>
        /// 物料产品分类仓储
        /// </summary>
        private readonly IRepository<MaterialType, int> _materialTypeRepository;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="materialTypeRepository">物料产品分类仓储</param>
        public MaterialTypeService(IRepository<MaterialType, int> materialTypeRepository)
        {
            _materialTypeRepository = materialTypeRepository;
        }

        ///// <summary>
        ///// 构建分类树形结构（递归）
        ///// </summary>
        //private List<MaterialType> BuildTree(List<MaterialType> all, int? parentId = null)
        //{
        //    return all
        //        .Where(c => c.ParentId == parentId)
        //        .Select(c => new MaterialType
        //        {
        //            MaterialTypeName = c.MaterialTypeName,
        //            Index = c.Index,
        //            ParentId = c.ParentId,
        //            State = c.State,
        //            CreateTime = c.CreateTime,
        //            // 递归子节点
        //            Children = BuildTree(all, c.Id)
        //        })
        //        .ToList();
        //}

        ///// <summary>
        ///// 获取分类树形结构（递归构建）
        ///// </summary>
        ///// <returns>分类树形列表，包含父子层级关系</returns>
        //public async Task<List<MaterialType>> GetTreeAsync()
        //{
        //    // 1. 先获取所有分类数据
        //    var all = await _materialTypeRepository.GetListAsync();
        //    // 2. 通过 BuildTree 方法递归构建树形结构（利用 ParentId 关联父子关系）
        //    return BuildTree(all);
        //}


        ///// <summary>
        ///// 构建分类树形结构（递归）
        ///// </summary>
        private List<MaterialTypeDTO> BuildTree(Dictionary<int?, List<MaterialType>> grouped, int? parentId = 0)
        {
            //if (!grouped.ContainsKey(parentId) || parentId == 0)
            //{
            //    return new List<MaterialTypeDTO>();
            //}
            if (!grouped.ContainsKey(parentId) || parentId == 0)
            {
                return new List<MaterialTypeDTO>();
            }

            return grouped[parentId].Select(c => new MaterialTypeDTO
            {
                Id = c.Id,
                MaterialTypeName = c.MaterialTypeName,
                Index = c.Index,
                ParentId = c.ParentId,
                State = c.State,
                CreateTime = c.CreateTime,
                Children = BuildTree(grouped, c.Id)
            }).ToList();
        }

        /// <summary>
        /// 获取分类树形结构（递归构建）
        /// </summary>
        /// <returns>分类树形列表，包含父子层级关系</returns>
        public async Task<List<MaterialTypeDTO>> GetTreeAsync()
        {
            // 1. 先获取所有分类数据
            var all = await _materialTypeRepository.GetListAsync();
            // 2. 对数据进行分组
            var grouped = all.GroupBy(c => c.ParentId).ToDictionary(g => g.Key, g => g.ToList());
            // 3. 通过 BuildTree 方法递归构建树形结构（利用 ParentId 关联父子关系）
            return BuildTree(grouped);
        }

        /// <summary>
        /// 选择要添加的父级
        /// </summary>
        /// <returns>返回数据</returns>
        public async Task<List<MaterialType>> GetMaterialTypes()
        {
            var info = await _materialTypeRepository.GetListAsync(x => x.ParentId == 0);
            return info;
        }

        /// <summary>
        /// 根据 ID 获取分类详情
        /// </summary>
        /// <param name="id">分类 ID</param>
        /// <returns>分类实体，若不存在则返回 null</returns>
        public async Task<MaterialType> GetByIdAsync(int id)
        {
            var info = await _materialTypeRepository.GetAsync(x => x.Id == id);
            // 使用仓储的 GetAsync 方法，通过 ID 精确查找分类
            return info;
        }

        /// <summary>
        /// 新增或修改分类
        /// </summary>
        /// <param name="entity">分类实体（新增时 ID=0，修改时需携带已有 ID）</param>
        /// <returns>操作是否成功（默认返回 true，实际可根据仓储返回值调整）</returns>
        public async Task<bool> SaveAsync(MaterialTypeAddDTO entity)
        {
            bool i = true;
            var info = ObjectMapper.Map<MaterialTypeAddDTO, MaterialType>(entity);
            if (entity.Id <= 0)
            {
                info.CreateTime = DateTime.Now;
                // 新增逻辑：ID=0 表示新记录，调用仓储的 InsertAsync 方法
                i = await _materialTypeRepository.InsertAsync(info) != null ? true : false;
            }
            else
            {
                // 修改逻辑：ID>0 表示更新已有记录，调用仓储的 UpdateAsync 方法
                i = await _materialTypeRepository.UpdateAsync(info) != null ? true : false;
            }
            return i;
        }

        /// <summary>
        /// 删除分类（递归删除所有子分类）
        /// </summary>
        /// <param name="id">待删除的分类 ID</param>
        /// <returns>操作是否成功（默认返回 true，实际可根据仓储返回值调整）</returns>
        public async Task<bool> DeleteAsync(int id)
        {
            // 1. 先递归删除所有子分类（避免数据残留）
            var children = await _materialTypeRepository.GetListAsync(c => c.ParentId == id);
            foreach (var child in children)
            {
                await DeleteAsync(child.Id);
            }

            // 2. 再删除当前分类
            await _materialTypeRepository.DeleteAsync(x => x.Id == id);
            return true;
        }

        /// <summary>
        /// 获取分类列表（支持搜索和状态筛选，不分页）
        /// </summary>
        /// <param name="keyword">分类名称关键词（模糊匹配）</param>
        /// <param name="isEnabled">是否启用（true=启用，false=禁用，null=不筛选）</param>
        /// <returns>分类列表</returns>
        public async Task<List<MaterialType>> GetPagedListAsync(string keyword = null, bool? isEnabled = null)
        {
            // 1. 获取可查询对象
            var queryable = await _materialTypeRepository.GetQueryableAsync();

            // 2. 应用筛选条件
            if (!string.IsNullOrEmpty(keyword))
                queryable = queryable.Where(c => c.MaterialTypeName.Contains(keyword));
            if (isEnabled.HasValue)
                queryable = queryable.Where(c => c.State == (isEnabled.Value ? 1 : 0)); // 假设 State=1 启用，0 禁用

            // 5. 返回结果
            return queryable.ToList();
        }






        /// <summary>
        /// 为节点构建子树（递归）
        /// </summary>
        private void BuildChildren(MaterialType node, List<MaterialType> allMaterials)
        {
            // 找到当前节点的直接子节点
            var children = allMaterials
                .Where(x => x.ParentId == node.Id)
                .OrderBy(x => x.Index)
                .ToList();

            // 设置子节点集合
            node.Children = children;

            // 递归处理每个子节点
            foreach (var child in children)
            {
                BuildChildren(child, allMaterials);
            }
        }


        /// <summary>
        /// 将树形结构拍平为列表
        /// </summary>
        private List<MaterialType> FlattenTree(List<MaterialType> tree)
        {
            var result = new List<MaterialType>();
            foreach (var node in tree)
            {
                result.Add(node);
                result.AddRange(FlattenTree(node.Children));
            }
            return result;
        }

        /// <summary>
        /// 分页查询分类列表（支持搜索和状态筛选）
        /// </summary>
        /// <param name="keyword">分类名称关键词（模糊匹配）</param>
        /// <param name="isEnabled">是否启用（true=启用，false=禁用，null=不筛选）</param>
        /// <param name="page">页码（从 1 开始）</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>分页结果（包含总数和当前页数据）</returns>
        public async Task<PagedResult<MaterialType>> GetPagedMaterialTypesAsync(string keyword = null, bool? isEnabled = null, int page = 1, int pageSize = 10)
        {
            // 1. 获取全量数据（注意：此处会加载所有数据到内存，性能问题后续优化）
            var query = await _materialTypeRepository.GetListAsync();

            // 2. 应用筛选条件
            if (!string.IsNullOrEmpty(keyword))
                query = (List<MaterialType>)query.Where(c => c.MaterialTypeName.Contains(keyword));
            if (isEnabled.HasValue)
                query = (List<MaterialType>)query.Where(c => c.State == (isEnabled.Value ? 1 : 0)); // 假设 State=1 启用，0 禁用

            // 3. 分页处理
            var total = query.Count(); // 计算总数
            var data = query
                .OrderBy(c => c.Index)          // 按 Index 排序（确保分页顺序稳定）
                .Skip((page - 1) * pageSize)    // 跳过前面的页
                .Take(pageSize);                // 获取当前页数据

            // 4. 返回分页结果
            return new PagedResult<MaterialType>
            {
                Total = total,
                Data = data.ToList()
            };
        }


        ///// <summary>
        ///// 构建分类树形结构（递归）
        ///// </summary>
        //private List<MaterialType> BuildTree(List<MaterialType> all, int? parentId = null)
        //{
        //    return all
        //        .Where(c => c.ParentId == parentId)
        //        .Select(c => new MaterialType
        //        {
        //            MaterialTypeName = c.MaterialTypeName,
        //            Index = c.Index,
        //            ParentId = c.ParentId,
        //            State = c.State,
        //            CreateTime = c.CreateTime,
        //            // 递归子节点
        //            Children = BuildTree(all, c.Id)
        //        })
        //        .ToList();
        //}

        ///// <summary>
        ///// 获取分类树形结构（递归构建）
        ///// </summary>
        ///// <returns>分类树形列表，包含父子层级关系</returns>
        //public async Task<List<MaterialType>> GetTreeAsync()
        //{
        //    // 1. 先获取所有分类数据
        //    var all = await _materialTypeRepository.GetListAsync();
        //    // 2. 通过 BuildTree 方法递归构建树形结构（利用 ParentId 关联父子关系）
        //    return BuildTree(all);
        //}


        /// <summary>
        //---------------------------------------------------------------------------------------------

        /// <summary>
        /// 获取分类树形结构（递归构建）
        /// </summary>
        public async Task<List<MaterialType>> GetTreeAsyncgrx()
        {
            // 1. 获取所有分类数据
            var allMaterials = await _materialTypeRepository.GetListAsync();

            // 2. 找到顶级节点（ParentId = 0 的节点）
            var roots = allMaterials.Where(x => x.ParentId == 0).OrderBy(x => x.Index).ToList();

            // 3. 构建每个顶级节点的子树
            foreach (var root in roots)
            {
                // 查找直接子节点
                var children = allMaterials
                    .Where(x => x.ParentId == root.Id)
                    .OrderBy(x => x.Index)
                    .ToList();

                // 为每个子节点构建其子树
                foreach (var child in children)
                {
                    BuildChildrengrx(child, allMaterials);
                }

                // 设置当前节点的子节点集合
                root.Children = children;
            }

            return roots;
        }

        /// <summary>
        /// 为节点构建子树（递归）
        /// </summary>
        private void BuildChildrengrx(MaterialType node, List<MaterialType> allMaterials)
        {
            // 找到当前节点的直接子节点
            var children = allMaterials
                .Where(x => x.ParentId == node.Id)
                .OrderBy(x => x.Index)
                .ToList();

            // 设置子节点集合
            node.Children = children;

            // 递归处理每个子节点
            foreach (var child in children)
            {
                BuildChildrengrx(child, allMaterials);
            }
        }

        /// <summary>
        /// 获取某节点的所有子节点（递归）
        /// </summary>
        public async Task<List<MaterialType>> GetAllChildrenAsyncgrx(int nodeId)
        {
            var allMaterials = await _materialTypeRepository.GetListAsync();
            var node = allMaterials.FirstOrDefault(m => m.Id == nodeId);
            if (node == null) return new List<MaterialType>();

            // 构建当前节点的子树
            BuildChildrengrx(node, allMaterials);

            // 返回展平的子节点列表
            return FlattenTreegrx(node.Children);
        }

        /// <summary>
        /// 获取节点路径（从根节点到指定节点）
        /// </summary>
        public async Task<List<MaterialType>> GetPathAsyncgrx(int nodeId)
        {
            var allMaterials = await _materialTypeRepository.GetListAsync();
            var path = new List<MaterialType>();
            var current = allMaterials.FirstOrDefault(m => m.Id == nodeId);

            while (current != null)
            {
                path.Insert(0, current);
                current = allMaterials.FirstOrDefault(m => m.Id == current.ParentId);
            }

            return path;
        }

        /// <summary>
        /// 将树形结构拍平为列表
        /// </summary>
        private List<MaterialType> FlattenTreegrx(List<MaterialType> tree)
        {
            var result = new List<MaterialType>();
            foreach (var node in tree)
            {
                result.Add(node);
                result.AddRange(FlattenTreegrx(node.Children));
            }
            return result;
        }

        /// <summary>
        /// 根据 ID 获取分类详情
        /// </summary>
        /// <param name="id">分类 ID</param>
        /// <returns>分类实体，若不存在则返回 null</returns>
        public async Task<MaterialType> GetByIdAsyncgrx(int id)
        {
            // 使用仓储的 GetAsync 方法，通过 ID 精确查找分类
            return await _materialTypeRepository.GetAsync(x => x.Id == id);
        }

        /// <summary>
        /// 新增或修改分类
        /// </summary>
        /// <param name="entity">分类实体（新增时 ID=0，修改时需携带已有 ID）</param>
        /// <returns>操作是否成功（默认返回 true，实际可根据仓储返回值调整）</returns>
        public async Task<bool> SaveAsyncgrx(MaterialTypeAddDTO entity)
        {
            bool i = true;
            var info = ObjectMapper.Map<MaterialTypeAddDTO, MaterialType>(entity);
            if (entity.Id <= 0)
            {
                info.CreateTime = DateTime.Now;
                // 新增逻辑：ID=0 表示新记录，调用仓储的 InsertAsync 方法
                i = await _materialTypeRepository.InsertAsync(info) != null ? true : false;
            }
            else
            {
                // 修改逻辑：ID>0 表示更新已有记录，调用仓储的 UpdateAsync 方法
                i = await _materialTypeRepository.UpdateAsync(info) != null ? true : false;
            }
            return true;
        }

        /// <summary>
        /// 删除分类（递归删除所有子分类）
        /// </summary>
        /// <param name="id">待删除的分类 ID</param>
        /// <returns>操作是否成功（默认返回 true，实际可根据仓储返回值调整）</returns>
        public async Task<bool> DeleteAsyncgrx(int id)
        {
            // 1. 先递归删除所有子分类（避免数据残留）
            var children = await _materialTypeRepository.GetListAsync(c => c.ParentId == id);
            foreach (var child in children)
            {
                await DeleteAsync(child.Id);
            }

            // 2. 再删除当前分类
            await _materialTypeRepository.DeleteAsync(x => x.Id == id);
            return true;
        }

        /// <summary>
        /// 分页查询分类列表（支持搜索和状态筛选）
        /// </summary>
        /// <param name="keyword">分类名称关键词（模糊匹配）</param>
        /// <param name="isEnabled">是否启用（true=启用，false=禁用，null=不筛选）</param>
        /// <param name="page">页码（从 1 开始）</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>分页结果（包含总数和当前页数据）</returns>
        public async Task<PagedResult<MaterialType>> GetPagedListAsyncgrx(string keyword = null, bool? isEnabled = null, int page = 1, int pageSize = 10)
        {
            // 1. 获取全量数据（注意：此处会加载所有数据到内存，性能问题后续优化）
            var query = await _materialTypeRepository.GetListAsync();

            // 2. 应用筛选条件
            if (!string.IsNullOrEmpty(keyword))
                query = (List<MaterialType>)query.Where(c => c.MaterialTypeName.Contains(keyword));
            if (isEnabled.HasValue)
                query = (List<MaterialType>)query.Where(c => c.State == (isEnabled.Value ? 1 : 0)); // 假设 State=1 启用，0 禁用

            // 3. 分页处理
            var total = query.Count(); // 计算总数
            var data = query
                .OrderBy(c => c.Index)          // 按 Index 排序（确保分页顺序稳定）
                .Skip((page - 1) * pageSize)    // 跳过前面的页
                .Take(pageSize);                // 获取当前页数据

            // 4. 返回分页结果
            return new PagedResult<MaterialType>
            {
                Total = total,
                Data = data.ToList()
            };
        }

    }
}
